package com.cskaoyan.javase.oop1._2reference;
/**
 * 我们第一次认识和了解引用数据类型是在数组这一章节
 * 我们通过JVM内存模型图和数组的初始化过程，知道：
 * 一个引用数据类型变量，分为两个部分：
 *      1.在栈上创建引用，它是一个局部变量。(这个引用也可以存在于其他对象中)
 *      2.在堆上开辟空间，创建对象。
 *      引用 + 对象
 *      栈上的引用通过存储堆上对象的地址和对象产生联系。
 *      对象是引用数据类型的实质，但我们只能通过栈上引用间接访问堆上对象。
 * 现在，我们已经学习过对象与类的知识点了，是时候进一步或者换一个角度去了解引用数据类型了。
 *
 * 先回顾一下，在Java基础语法部分，我们给出的数据类型的概念/定义：
 * 数据类型： 表示的是一组数据的集合，和基于该数据集合的一组合法操作。
 * 数据类型 = 数据 + 操作
 *
 * 这个定义套在基本数据类型上，实在再合适不过了。
 * 比如int类型，它的取值范围是固定的，有限的，能够做的操作（加减乘除等）也是被限制的。
 *
 * 那么这个定义能不能套在引用数据类型中呢？
 * 能否用数据类型的概念来统一基本数据类型和引用数据类型呢？
 *
 * 接下来我们需要分析一下，这个问题。
 * 在上一节类的定义中，类中的成员包括：
 *      1.成员变量(数据,属性)
 *      2.成员方法(操作,行为)
 * 成员变量本质上就是数据，成员方法本质上就是操作，那么假设做以下类比：
 *      1.数据的集合： 类中成员变量的集合
 *      2.操作的集合： 类中成员方法的集合
 *
 * 于是，就可以做出以下总结：
 *      一个类的定义，实际上就是定义了一种全新的数据类型，一种自定义的数据类型。这种完全不同于基本数据类型的数据类型，我们称之为"引用数据类型"。
 *      定义一个类,就是定义一个新的,自定义的引用数据类型
 * 注：当然引用数据类型不仅仅包括类，但大体上上述说法是没问题的。
 *
 *
 * 引用数据类型和基本数据类型的不同点:
 * 当我们在程序中使用一个基本数据类型时，由于基本数据类型是JVM当中已经预先定义好的（所以基本数据类型叫"内置数据类型"）,所以基本数据类型变量,JVM能够正常开辟空间存储和使用它.
 *
 * 但是引用数据类型不同,它可能是我们自定义的新的数据类型,比如自定义一个Student类,现在需要JVM创建它的对象,这时JVM是如何了解该类型的呢?它能未卜先知吗?
 *
 * 所以对于引用数据类型而言,JVM在开辟空间创建它(的对象)和使用它之前,需要一个了解/认识该类型的过程.
 * 这个过程就是Java中的,类加载的过程.
 * 类加载是JVM认识了解某个类型的过程.
 *
 * 关于类加载：
 *      1.类加载的具体过程，我们后面会详细学习。这里我们先不用了解它的详细过程。
 *      2.类加载是通过I/O流的形式,将某个类的class文件,读取进JVM内存的方法区,然后通过一系列流程完成.
 *          I/O最大的问题是效率很低(相对于CPU和内存而言)
 *          所以对于Java程序而言,类加载应该是越多越好,还是越少越好? 尽量越少,这样程序的执行效率会更高
 *          当Java程序启动时,是选择一股脑将所有类全部加载,还是等到用到的时候再加载? Java的类加载是用到的时候再加载
 *          我们把Java类加载以上描述的机制,称之为"懒加载":
 *          只有当迫不得已必须要类加载某个类型时,不类加载某个类型程序就无法继续执行时,JVM才会进行类加载
 *
 *      3.在Java代码中,我们把JVM不得不类加载某个类的场景/代码,称之为"类加载的时机"
 *      目前我们已经知道的类加载的时机:
 *          a.启动main方法,触发启动类的类加载,类加载结束后,才会启动main方法.类加载在前,启动main方法在后
 *          b.new创建一个类的对象,必须进行该类的类加载,而且类加载在前,创建对象在后
 *      碰到"类加载的时机",JVM会先进行该类的类加载,然后再去执行"类加载的时机"
 *
 *
 *      4.(重点)类加载是JVM了解/认识一个类型的过程,那么对于某个类而言,在一次程序的启动过程中
 *          类加载最多只有一次
 *          也就是说一个类要么不进行类加载
 *
 *
 * @since 09:32
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    // 启动Demo类的main方法,Demo类就会进行类加载
    public static void main(String[] args) {
        // JVM先类加载A,类加载A结束后,才开始new对象
        A a = new A();

        // 再次创建A的对象,不会再一次类加载
        A a1 = new A();

        // 启动main方法已经触发过类加载了,类加载已经结束了,所以这里不会再次类加载了.
        Demo d = new Demo();
    }
}

// 一个Java文件中,可以有很多个class类,这些class类在编译后,都会有自己独立的class文件
class A {
}
// 该程序中没有使用到B类,虽然它也会有一个编译后的B.class文件,但是它没有进行类加载
class B{}